package com.boolib.shopadmin.config.shiro.config;


import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;


import com.boolib.shopadmin.config.shiro.commons.MySessionDao;
import com.boolib.shopadmin.config.shiro.filter.SystemLogoutFilter;
import com.boolib.shopadmin.config.shiro.realm.MyRealm;
import lombok.extern.slf4j.Slf4j;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {





    /**
     * 设置安全管理器
     * @return
     */

    @Bean
    public SecurityManager securityManager(){

        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

        log.info("Manager加载Realm");


        defaultWebSecurityManager.setSessionManager(sessionManager());

        defaultWebSecurityManager.setCacheManager(ehCacheManager());


        defaultWebSecurityManager.setRealm(realm());

        return defaultWebSecurityManager;

    }



    /**
     * 设置shiro过滤链
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //把安全管理器加入到factoryBean中
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        shiroFilterFactoryBean.setUnauthorizedUrl("error/NoPermission");


        //设置登录页面
        shiroFilterFactoryBean.setLoginUrl("/admin/login");

        //设置登录成功跳转页面
        shiroFilterFactoryBean.setSuccessUrl("/index");




        //配置自定义map
        Map<String , Filter>  filterMap = new LinkedHashMap<>();



        filterMap.put("logout" ,new SystemLogoutFilter());


        Map <String,String> filterChain = new LinkedHashMap<>();


        filterChain.put("/admin/logout","logout");

        filterChain.put("/assets/**","anon");

        filterChain.put("/menu/**","anon");

        filterChain.put("/session/**","anon");

        filterChain.put("/druid/**","anon");

        //filterChain.put("/admin/register","anon");

        filterChain.put("/admin/forgetPassword","anon");

        filterChain.put("/admin/alterPasswordBeforeLogin","anon");

        filterChain.put("/**","authc");



        shiroFilterFactoryBean.setFilters(filterMap);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChain);


        return shiroFilterFactoryBean;



    }


    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

//
//    //自定义加密
//    @Bean
//    public CredentialsMatcher credentialsMatcher(){
//        MyCredentials hashedCredentialsMatcher = new MyCredentials();
//        hashedCredentialsMatcher.setHashAlgorithmName("md5");
//        hashedCredentialsMatcher.setHashIterations(1);
//        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
//        return hashedCredentialsMatcher;
//    }




    //自定义realm
    @Bean
    public Realm realm(){

        MyRealm myRealm = new MyRealm();

        myRealm.setAuthenticationCachingEnabled(true);

        myRealm.setAuthorizationCachingEnabled(true);

        myRealm.setCachingEnabled(true);

       // myRealm.setCredentialsMatcher(credentialsMatcher());

        return myRealm;

    }


    @Bean
    public EhCacheManager ehCacheManager(){

        EhCacheManager em = new EhCacheManager();

        em.setCacheManagerConfigFile("classpath:./cache/ehcache.xml");

        return em;
    }



    @Bean
    public SessionIdGenerator sessionIdGenerator(){
        return new JavaUuidSessionIdGenerator();
    }



    @Bean
    public MySessionDao mySessionDao (){
        MySessionDao mySessionDao = new MySessionDao();
        mySessionDao.setSessionIdGenerator(sessionIdGenerator());
        mySessionDao.setActiveSessionsCacheName("sessionList");
        return mySessionDao;
    }



    @Bean
    public SessionManager sessionManager (){
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        defaultWebSessionManager.setSessionIdCookieEnabled(true);
        defaultWebSessionManager.setDeleteInvalidSessions(true);
        defaultWebSessionManager.setGlobalSessionTimeout(180000);
        defaultWebSessionManager.setSessionDAO(mySessionDao());
        defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);
        defaultWebSessionManager.setSessionValidationInterval(60000);
        defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
        return defaultWebSessionManager;
    }





    /**
     *  开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }



    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

}
